

#ifndef __metaH__
#define __metaH__

namespace Meta {
	/// The Meta::Null type.
	struct Null {
		inline bool operator == (const Null& a) const {
			return true;
		};
	};

	/// Argument type traits
	template <class T>
	struct ValueTraits {
		typedef T&       tRef;
		typedef const T& tConstRef;
		typedef T                 tStorage;
	};
	template <class T>
	struct ValueTraits<T&> {
		typedef T&       tRef;
		typedef const T& tConstRef;
		typedef T                tStorage;
	};
	template <class T>
	struct ValueTraits<const T> {
		typedef T& tRef;
		typedef const T& tConstRef;
		typedef T          tStorage;
	};
	template <class T>
	struct ValueTraits<const T&> {
		typedef T& tRef;
		typedef const T& tConstRef;
		typedef T          tStorage;
	};

	/// Class traits
	template <class T>
	struct ClassTraits {
		typedef typename T::tRef tPtr;
		typedef T tClass;
	};
	template <class T>
	struct ClassTraits<T *> {
		typedef T * tPtr;
		typedef T tClass;
	};


	/// Fetching real values from metavalues
	template <class T>
	struct Value {
		typedef T tValue;

		inline static typename ValueTraits<tValue>::tConstRef get(typename ValueTraits<tValue>::tConstRef t) {
			return t;
		};
	};
	
	/// Iterates to parent type's get/set methods.
#	define META_VALUE_DEFAULT(Type, ParentType) struct Value<Type >: public Value<ParentType > {};

	/// Defines a getter method for a dator
#	define META_VALUE(Type, ValueType, ValueExpr) \
	struct Value<Type> : public Value<ValueType > { \
		inline static typename ValueTraits<ValueType >::tConstRef get(typename ValueTraits<Type >::tConstRef that) { \
			return typename Value<ValueType >::get(ValueExpr); \
		}; \
	};


	template <class T>
	struct ListTraits {
		typedef typename T::tHead Head;
		typedef typename T::tTail Tail;
	};
	template <>
	struct ListTraits<Null> {
		typedef Null Head;
		typedef Null Tail;
	};

	namespace List {
		/// Removes leading Nulls from the list
		template <class _xs>
		struct Trim {
			typedef ListTraits<_xs> tList;
			
			template <class _orig, class _y, class _ys>
			struct Impl {
				typedef _orig Value;
			};
			template <class _orig, class _ys>
			struct Impl<_orig, Null, _ys> {
				typedef ListTraits<_ys> tList;
				typedef typename Impl<_ys, typename tList::Head, typename tList::Tail>::Value Value;
			};
			template <class _orig, class _y>
			struct Impl<_orig, _y, Null> {
				typedef _orig Value;
			};
			template <class _orig>
			struct Impl<_orig, Null, Null> {
				typedef Null Value;
			};

			typedef typename Impl<_xs, typename tList::Head, typename tList::Tail>::Value Value;
		};
	};
};


#define __DELEGATE_OPERATORS(Type, Value, __typename) public:\
	template <class _DELEGATE_OP_TYPE> \
	inline __typename Meta::ValueTraits<Type>::tStorage operator + (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (*this + v); \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline void operator += (__typename Meta::ValueTraits<Type>::tConstRef v) { \
		(Value) += v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline __typename Meta::ValueTraits<Type>::tStorage operator - (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (*this - v); \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline void operator -= (__typename Meta::ValueTraits<Type>::tConstRef v) { \
		(Value) -= v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline __typename Meta::ValueTraits<Type>::tStorage operator * (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (*this * v); \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline void operator *= (__typename Meta::ValueTraits<Type>::tConstRef v) { \
		(Value) *= v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline __typename Meta::ValueTraits<Type>::tStorage operator / (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (*this / v); \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline void operator /= (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) { \
		(Value) /= v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline bool operator == (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (Value) == v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline bool operator != (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (Value) != v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline bool operator < (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (Value) < v; \
	}; \
	template <class _DELEGATE_OP_TYPE> \
	inline bool operator > (__typename Meta::ValueTraits<_DELEGATE_OP_TYPE>::tConstRef v) const { \
		return (Value) > v; \
	}; \
	inline __typename Meta::ValueTraits<Type>::tRef operator -> () { \
		return (Value); \
	}; \
	inline __typename Meta::ValueTraits<Type>::tConstRef operator -> () const { \
		return (Value); \
	};

/// Delegates standard operators to a class member of type Type, given
/// by Value.
#define DELEGATE_OPERATORS(Type, Value) __DELEGATE_OPERATORS(Type, Value, )
#define DELEGATE_OPERATORS_IN_TPL(Type, Value) __DELEGATE_OPERATORS(Type, Value, typename)

#endif